<?php
/**
 * Random handy functions used throughout SleekPHP's core
 */

# Here come the functions...

/**
 * Turns $url into valid URL
 *
 * @param string $url
 */
function urlize ($url) {
	return preg_replace('/[^a-z0-9_-]/', '', str_replace(array('å', 'ä', 'ö', ' '), array('a', 'a', 'o', '-'), strtolower($url)));
}

/**
 * Returns the current page URL $withQry or not
 *
 * @param bool $withQry
 */
function currPageURL ($withQry = true) {
	$isHTTPS	= (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on');
	$port		= (isset($_SERVER['SERVER_PORT']) && ((!$isHTTPS && $_SERVER['SERVER_PORT'] != "80") || ($isHTTPS && $_SERVER['SERVER_PORT'] != '443')));
	$port		= ($port) ? ':' . $_SERVER['SERVER_PORT'] : '';
	$url		= ($isHTTPS ? 'https://' : 'http://') . $_SERVER['SERVER_NAME'] . $port . $_SERVER['REQUEST_URI'];
	$qryStart	= strpos($url, '?');

	if ($qryStart and !$withQry) {
		return substr($url, 0, $qryStart);
	}

	return $url;
}

/**
 * Trimmed, unique, not null $arr(ay)
 *
 * @param array $arr
 */
function tunnArray ($arr) {
	if (is_array($arr)) {
		$arr = array_map('trim', $arr);	# trim
		$arr = array_unique($arr);		# unique
		$arr = array_filter($arr);		# remove false/empty

		return $arr;
	}

	return false;
}

/**
 * Fixes camelCase $str to camel-Case (or whatever $separator user wants)
 *
 * @param string $str
 * @param string $separator
 */
function ccFix ($str, $separator = '-') {
	$str = preg_replace('/([A-Z0-9]+)/', "$separator\\1", $str);

	if (substr($str, 0, 1) == $separator) {
		return substr($str, 1);
	}

	return $str;
}

/**
 * Dumps $foo with var_dump, but changes content-type and dies
 *
 * @param mixed $foo
 */
function debug ($foo) {
	header('Content-type: text/plain; charset=utf-8');

	if (is_array($foo)) {
		echo '# ' . count($foo) . " elements #\n";
	}

	var_dump($foo);
	die;
}

/**
 * Like str_replace replaces $needle with $replace in $haystack
 * but _unlike_ str_replace only does it for the _first_ occurnce of $needle
 *
 * @param string $needle
 * @param string $replace
 * @param string $haystack
 */
function str_replace_once ($needle, $replace, $haystack) {
	if ($pos = strpos($haystack, $needle)) {
		return substr_replace($haystack, $replace, $pos, strlen($needle));
	}

	return $haystack;
}

/**
 * Extracts key/value pairs from $str
 *
 * @param string $str
 */
function extractKeyValArray ($str) {
	$lines	= explode("\n", $str);
	$data	= array();
	$key	= false;

	foreach ($lines as $line) {
		if (substr($line, 0, 1) == '@') {
			preg_match('/^@(.*?)( |$)(.*?)$/', $line, $matches);

			$key = $matches[1];

			if (isset($matches[3])) {
				$data[$key] = $matches[3];
			}
			else {
				$data[$key] = '';
			}
		}
		else if ($key) {
			$data[$key] .= "$line\n";
		}
	}

	array_walk($data, create_function('&$val', '$val = trim($val);')); # TODO: not array_map('trim', $data);?

	return $data;
}

/**
 * Redirects to $url and dies
 *
 * @param string $url
 */
function redirect ($to) {
	header('Location: ' . $to);
	die("Redirect failed, please go to <a href=\"$to\">$to</a>");
}

/**
 * Extracts data about "components" (styles, modules etc)
 *
 * @param string $name
 * @param string $path
 */
function getComponentData ($name, $path, $type = 'Modules') {
	# If $path isn't a path it's assumed to be a site name
	if (!strstr($path, '/')) {
		$path = DOCROOT . "Sites/$path/$type/$name";
	}

	if (!file_exists("$path/$name.info")) {
		return false;
	}

	$data = extractKeyValArray(file_get_contents("$path/$name.info"));

	# Add site name
	preg_match("|Sites/(.*?)/$type|", $path, $matches);

	$data['site']		= new Site($matches[1]);
	$data['site']		= $data['site']->getInfo();
	$data['site_name']	= $data['site']['name'];
	$data['site_slug']	= $data['site']['slug'];

	# Add potential thumbnail
	foreach (array('jpg', 'png', 'gif') as $ext) {
		$thumbPath = "$path/$name.$ext";

		if (file_exists($thumbPath)) {
			$data['thumb']['webpath'] = WEBROOT . 'Sites/' . $data['site']['name'] . "/$type/$name/$name.$ext";
			$data['thumb']['docpath'] = DOCROOT . 'Sites/' . $data['site']['name'] . "/$type/$name/$name.$ext";

			break;
		}
	}

	# Always set name to module name
	$data['name'] = $name;

	# Make sure title is set
	if (!isset($data['title'])) {
		$data['title'] = $data['name'];
	}

	# Urlize name
	$data['slug'] = urlize($data['name']);

	# Download URL
	$data['download_url'] = 'http://code.google.com/p/sleekphp/source/browse/trunk#trunk%2FSites%2F' . $data['site']['name'] . '%2F' . $type . '%2F' . $data['name'];

	return $data;
}

/**
Validate an email address.
Provide email address (raw input)
Returns true if the email address has the email 
address format and the domain exists.
*/
function validEmail($email)
{
   $isValid = true;
   $atIndex = strrpos($email, "@");
   if (is_bool($atIndex) && !$atIndex)
   {
      $isValid = false;
   }
   else
   {
      $domain = substr($email, $atIndex+1);
      $local = substr($email, 0, $atIndex);
      $localLen = strlen($local);
      $domainLen = strlen($domain);
      if ($localLen < 1 || $localLen > 64)
      {
         // local part length exceeded
         $isValid = false;
      }
      else if ($domainLen < 1 || $domainLen > 255)
      {
         // domain part length exceeded
         $isValid = false;
      }
      else if ($local[0] == '.' || $local[$localLen-1] == '.')
      {
         // local part starts or ends with '.'
         $isValid = false;
      }
      else if (preg_match('/\\.\\./', $local))
      {
         // local part has two consecutive dots
         $isValid = false;
      }
      else if (!preg_match('/^[A-Za-z0-9\\-\\.]+$/', $domain))
      {
         // character not valid in domain part
         $isValid = false;
      }
      else if (preg_match('/\\.\\./', $domain))
      {
         // domain part has two consecutive dots
         $isValid = false;
      }
      else if (!preg_match('/^(\\\\.|[A-Za-z0-9!#%&`_=\\/$\'*+?^{}|~.-])+$/', str_replace("\\\\","",$local)))
      {
         // character not valid in local part unless 
         // local part is quoted
         if (!preg_match('/^"(\\\\"|[^"])+"$/', str_replace("\\\\","",$local)))
         {
            $isValid = false;
         }
      }
      if ($isValid && !(checkdnsrr($domain,"MX") || checkdnsrr($domain,"A")))
      {
         // domain not found in DNS
         $isValid = false;
      }
   }
   return $isValid;
}
